use std::{
    env::{split_paths, var_os},
    ffi::OsStr,
    path::PathBuf,
};

pub struct Cmd {
    path: PathBuf,
}
impl Cmd {
    pub fn path(&self) -> &PathBuf {
        &self.path
    }
    pub fn find(_cmd_name: &str) -> Option<Self> {
        let key = "PATH";
        let cmd_file = OsStr::new(_cmd_name);
        let paths = match var_os(key) {
            Some(x) => x,
            None => return None,
        };
        for p in split_paths(&paths) {
            if p.is_file() && p.file_name() == Some(cmd_file) && p.exists() {
                return Some(Self { path: p });
            }
            if p.is_dir() {
                if let Some(x) = Self::find_in(&p, _cmd_name) {
                    return Some(x);
                }
            }
        }
        None
    }
    pub fn find_in(p: &std::path::PathBuf, cmd_file: &str) -> Option<Self> {
        let cmd_file = OsStr::new(cmd_file);
        let dir_content = match p.read_dir() {
            Ok(x) => x,
            Err(_) => return None,
        };
        for entry in dir_content {
            let x = match entry {
                Ok(x) => x,
                Err(_) => return None,
            };
            if x.path().file_name() == Some(cmd_file) {
                return Some(Self { path: x.path() });
            }
        }
        None
    }
}
